import React, { useState, useEffect } from "react";
import {
  Modal,
  StyleSheet,
  View,
  TouchableWithoutFeedback,
  LayoutChangeEvent,
  Dimensions,
  Platform,
  ViewStyle,
} from "react-native";
import { MenuProps, MenuPosition, MenuItemConfig } from "./types";
import MenuRenderer, { defaultIconRenderer } from "./MenuRenderer";
import { useTheme } from "@/contexts/ThemeContext";

// 获取屏幕尺寸用于边界计算
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("window");

const DEFAULT_OFFSET = { x: 0, y: 0 };
const DEFAULT_CONTAINER_STYLE = {};

/**
 * @author BelovedLYC
 * Menu组件 - 提供可配置、支持多级子菜单的弹出式菜单
 *
 * 特性:
 * - 支持两种使用方式：配置式和子组件式
 * - 支持自动定位，相对于触发元素的八个方向
 * - 支持多级子菜单，最多支持两级嵌套
 * - 支持自定义样式和主题
 * - 支持自定义图标渲染
 * - 提供完整的类型定义
 *
 * @component
 * @example
 * ```tsx
 * // 方式1: 基于配置的使用方式
 * import { useState, useRef } from 'react';
 * import { View, TouchableOpacity } from 'react-native';
 * import { Ionicons } from '@expo/vector-icons';
 * import Menu, { MenuPosition, MenuItemConfig } from '../components/global/Menu';
 *
 * // 菜单配置
 * const MENU_CONFIG: MenuItemConfig[] = [
 *   {
 *     id: "settings",
 *     label: "设置",
 *     icon: "settings-outline",
 *     onPress: "settings"
 *   },
 *   {
 *     id: "share",
 *     label: "分享",
 *     icon: "share-outline",
 *     children: [
 *       {
 *         id: "wechat",
 *         label: "微信",
 *         icon: "logo-wechat",
 *         onPress: "share-wechat"
 *       }
 *     ]
 *   }
 * ];
 *
 * function MyComponent() {
 *   const [menuVisible, setMenuVisible] = useState(false);
 *   const buttonRef = useRef(null);
 *
 *   const handleItemPress = (item) => {
 *     console.log(`选择了: ${item.id}`, item);
 *     // 处理菜单项选择
 *   };
 *
 *   return (
 *     <View>
 *       <TouchableOpacity
 *         ref={buttonRef}
 *         onPress={() => setMenuVisible(true)}
 *       >
 *         <Ionicons name="menu" size={24} color="black" />
 *       </TouchableOpacity>
 *
 *       <Menu
 *         visible={menuVisible}
 *         onClose={() => setMenuVisible(false)}
 *         position={MenuPosition.BOTTOM}
 *         triggerRef={buttonRef}
 *         items={MENU_CONFIG}
 *         onItemPress={handleItemPress}
 *       />
 *     </View>
 *   );
 * }
 *
 * // 方式2: 使用子组件的方式
 * import { MenuItem } from '../components/global/Menu';
 *
 * function MyComponentWithChildren() {
 *   const [menuVisible, setMenuVisible] = useState(false);
 *   const buttonRef = useRef(null);
 *
 *   return (
 *     <View>
 *       <TouchableOpacity
 *         ref={buttonRef}
 *         onPress={() => setMenuVisible(true)}
 *       >
 *         <Ionicons name="menu" size={24} color="black" />
 *       </TouchableOpacity>
 *
 *       <Menu
 *         visible={menuVisible}
 *         onClose={() => setMenuVisible(false)}
 *         position={MenuPosition.BOTTOM}
 *         triggerRef={buttonRef}
 *       >
 *         <MenuItem
 *           label="设置"
 *           leftIcon={<Ionicons name="settings-outline" size={20} color="#333" />}
 *           onPress={() => console.log('设置')}
 *         />
 *         <MenuItem
 *           label="关于"
 *           leftIcon={<Ionicons name="information-circle-outline" size={20} color="#333" />}
 *           onPress={() => console.log('关于')}
 *         />
 *       </Menu>
 *     </View>
 *   );
 * }
 * ```
 */
const Menu: React.FC<MenuProps> = ({
  items,
  children,
  visible,
  onClose,
  position = MenuPosition.BOTTOM,
  triggerRef,
  triggerLayout,
  containerStyle = DEFAULT_CONTAINER_STYLE,
  itemStyle,
  itemTextStyle,
  width = 180,
  showShadow = true,
  closeOnSelect = true,
  renderIcon = defaultIconRenderer,
  offset = DEFAULT_OFFSET,
  onItemPress,
}) => {
  const { colors } = useTheme();
  const [menuLayout, setMenuLayout] = useState<any>(null);
  const [triggerRect, setTriggerRect] = useState<any>(null);
  const [menuStyle, setMenuStyle] = useState<any>({});

  /**
   * 获取触发元素位置
   * 当菜单可见时，测量触发元素的位置，用于计算菜单的显示位置
   */
  useEffect(() => {
    if (!visible) return;

    if (triggerLayout) {
      setTriggerRect(triggerLayout);
    } else if (triggerRef?.current) {
      triggerRef.current.measureInWindow(
        (x: number, y: number, width: number, height: number) => {
          setTriggerRect({ x, y, width, height });
        }
      );
    }
  }, [visible, triggerRef, triggerLayout]);

  /**
   * 计算菜单位置
   * 根据触发元素位置、菜单尺寸和position属性，计算菜单的最终位置
   * 并考虑屏幕边界，防止菜单溢出屏幕
   */
  useEffect(() => {
    // 如果没有触发元素位置或菜单尺寸，无法计算位置
    if (!triggerRect || !menuLayout) return;

    let left = 0;
    let top = 0;

    // 如果是自定义模式，直接使用containerStyle定义位置
    if (position === MenuPosition.CUSTOM) {
      return;
    }

    // 根据所需位置计算菜单的展示位置
    switch (position) {
      case MenuPosition.TOP:
        left = triggerRect.x + (triggerRect.width - menuLayout.width) / 2;
        top = triggerRect.y - menuLayout.height;
        break;
      case MenuPosition.BOTTOM:
        left = triggerRect.x + (triggerRect.width - menuLayout.width) / 2;
        top = triggerRect.y + triggerRect.height;
        break;
      case MenuPosition.LEFT:
        left = triggerRect.x - menuLayout.width;
        top = triggerRect.y + (triggerRect.height - menuLayout.height) / 2;
        break;
      case MenuPosition.RIGHT:
        left = triggerRect.x + triggerRect.width;
        top = triggerRect.y + (triggerRect.height - menuLayout.height) / 2;
        break;
      case MenuPosition.TOP_LEFT:
        left = triggerRect.x;
        top = triggerRect.y - menuLayout.height;
        break;
      case MenuPosition.TOP_RIGHT:
        left = triggerRect.x + triggerRect.width - menuLayout.width;
        top = triggerRect.y - menuLayout.height;
        break;
      case MenuPosition.BOTTOM_LEFT:
        left = triggerRect.x;
        top = triggerRect.y + triggerRect.height;
        break;
      case MenuPosition.BOTTOM_RIGHT:
        left = triggerRect.x + triggerRect.width - menuLayout.width;
        top = triggerRect.y + triggerRect.height;
        break;
    }

    // 应用偏移量
    left += offset.x;
    top += offset.y;

    // 确保菜单不会超出屏幕边界
    if (left < 0) left = 0;
    if (left + menuLayout.width > SCREEN_WIDTH)
      left = SCREEN_WIDTH - menuLayout.width;
    if (top < 0) top = 0;
    if (top + menuLayout.height > SCREEN_HEIGHT)
      top = SCREEN_HEIGHT - menuLayout.height;

    // 设置菜单样式
    setMenuStyle({
      position: "absolute",
      width,
      left,
      top,
      backgroundColor: colors.backgroundLight,
      ...getMenuShadowStyle(showShadow, colors.card.shadow),
    });
  }, [
    triggerRect,
    menuLayout,
    position,
    width,
    showShadow,
    offset,
    colors,
    containerStyle,
  ]);

  /**
   * 菜单布局变化处理
   * 当菜单组件布局发生变化时，保存新的布局信息
   */
  const handleMenuLayout = (event: LayoutChangeEvent) => {
    const layout = event.nativeEvent.layout;
    setMenuLayout(layout);
  };

  /**
   * 处理菜单项点击
   * 当菜单项被点击时执行相应的回调，并根据配置决定是否关闭菜单
   */
  const handleMenuItemSelect = (item: MenuItemConfig) => {
    // 如果有自定义处理函数，调用它
    if (onItemPress) {
      onItemPress(item);
    }

    // 如果有onPress回调函数，直接调用
    if (typeof item.onPress === "function") {
      item.onPress();
    }

    // 选择后自动关闭菜单
    if (closeOnSelect) {
      onClose();
    }
  };

  /**
   * 获取菜单阴影样式
   * 根据平台不同返回iOS的shadow或Android的elevation
   */
  const getMenuShadowStyle = (
    show: boolean,
    shadowColor: string
  ): ViewStyle => {
    if (!show) return {};
    return Platform.select({
      ios: {
        shadowColor,
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.2,
        shadowRadius: 4,
      },
      android: {
        elevation: 5,
        shadowColor,
      },
      default: {},
    });
  };

  /**
   * 渲染菜单内容
   * 根据传入的配置决定如何渲染菜单内容
   * - 如果有children，直接渲染children
   * - 如果有items配置，使用MenuRenderer渲染配置的菜单项
   */
  const renderMenuContent = () => {
    // 优先使用children，如果没有则使用items数组
    if (children) {
      return children;
    } else if (items && items.length > 0) {
      return (
        <MenuRenderer
          items={items}
          onItemSelect={handleMenuItemSelect}
          iconRenderer={renderIcon}
          itemStyle={itemStyle}
          itemTextStyle={itemTextStyle}
          closeOnSelect={closeOnSelect}
        />
      );
    }
    return null;
  };

  return (
    <Modal
      transparent
      visible={visible}
      animationType="none"
      onRequestClose={onClose}
    >
      <TouchableWithoutFeedback onPress={onClose}>
        <View style={styles.modalOverlay}>
          <TouchableWithoutFeedback>
            <View
              style={[styles.menuContainer, menuStyle, containerStyle]}
              onLayout={handleMenuLayout}
            >
              {renderMenuContent()}
            </View>
          </TouchableWithoutFeedback>
        </View>
      </TouchableWithoutFeedback>
    </Modal>
  );
};

const styles = StyleSheet.create({
  modalOverlay: {
    flex: 1,
    backgroundColor: "rgba(0, 0, 0, 0)",
  },
  menuContainer: {
    borderRadius: 8,
    overflow: "hidden",
  },
});

export default Menu;
